home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #46 (Jul 89) / Window Menu Code / Window Menu.p < prev    next >
Text File  |  1989-01-19  |  8KB  |  300 lines

  1. (*******************************************************************
  2.     
  3.     Window Menu.p
  4.     
  5.     MDEF for dynamic Window menu demo.
  6.     
  7.     (c) 1988, by Clifford Story & Attic Software
  8.     
  9. *******************************************************************)
  10.     
  11. unit WDEF;
  12.     
  13. (******************************************************************)
  14.     
  15. interface
  16.     
  17. (******************************************************************)
  18.     
  19.     uses memtypes, quickdraw, osintf, toolintf, Common;
  20.     
  21. (******************************************************************)
  22.     
  23.     procedure menudef(message : integer; themenu : MenuHandle;
  24.                     var menurect : Rect; hitpoint : Point;
  25.                     var whichitem : integer);
  26.     
  27. (******************************************************************)
  28.     
  29. implementation
  30.     
  31. (******************************************************************)
  32.     
  33.     type
  34.         
  35.         QDrecord                =    record
  36.             randSeed            :    long;
  37.             screenBits        :    BitMap;
  38.             arrow                :    Cursor;
  39.             dkGray            :    Pattern;
  40.             ltGray            :    Pattern;
  41.             gray                :    Pattern;
  42.             black                :    Pattern;
  43.             white                :    Pattern;
  44.             thePort            :    GrafPtr;
  45.         end;
  46.         QDpointer            =    ^QDrecord;
  47.     
  48. (******************************************************************)
  49.     
  50.     procedure menudraw(themenu : MenuHandle; var menurect : Rect); forward;
  51.     procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
  52.                     hitpoint : Point; var whichitem : integer); forward;
  53.     procedure menusize(themenu : MenuHandle); forward;
  54.     
  55. (******************************************************************)
  56.     
  57.     {$R-}
  58.     {$SC+}
  59.     
  60. (*******************************************************************
  61.     
  62.     menudef
  63.     -------
  64.     
  65.     An MDEF is called to do three different things:  draw the menu,
  66.     hit-test a mouse location, or calculate the menu dimensions.
  67.     The “message” parameter determines which service is requested,
  68.     so the MDEF simply branches on “message” to specialized routines
  69.     that handle the specific functions.
  70.     
  71. *******************************************************************)
  72.     
  73.     procedure menudef(message : integer; themenu : MenuHandle;
  74.                     var menurect : Rect; hitpoint : Point;
  75.                     var whichitem : integer);
  76.         
  77.         begin
  78.  
  79.             case message of
  80.                 mDrawMsg        :    menudraw(themenu, menurect);
  81.                 mChooseMsg    :    menuchoose(themenu, menurect,
  82.                                                     hitpoint, whichitem);
  83.                 mSizeMsg        :    menusize(themenu);
  84.             end;
  85.         
  86.         end;
  87.     
  88. (******************************************************************
  89.     
  90.     QDglobals
  91.     ---------
  92.     
  93.     The QDglobals function returns a pointer to the QuickDraw
  94.     globals.  This allows procedure definitions and desk accessories
  95.     to access the QD globals even though they can't call InitGraf.
  96.  
  97. ******************************************************************)
  98.  
  99.     function QDglobals : QDpointer;
  100.         
  101.         var
  102.             thepointer        :    longpointer;
  103.         
  104.         begin
  105.             
  106.             thepointer := longpointer(currenta5);
  107.             thepointer := longpointer(thepointer^);
  108.             QDglobals := QDpointer(long(thepointer^)
  109.                             - sizeof(QDrecord) + sizeof(GrafPtr));
  110.         
  111.         end;
  112.     
  113. (*******************************************************************
  114.     
  115.     menudraw
  116.     --------
  117.     
  118.     The “menudraw” routine draws the menu.
  119.     
  120.     The first item is the “Draw Front Window” command, and the
  121.     second is the separating line before the list of window.  If
  122.     the first item is disabled, then it should be grayed out, by
  123.     painting over it with gray.
  124.     
  125.     The remaining items are found in the window list that is kept
  126.     by the system.  The low-memory global “windowlist” contains a
  127.     pointer to the front window.  Each window record includes in
  128.     turn a pointer to the next window in the list; the last window's
  129.     pointer is nil.
  130.     
  131.     Drawing the menu, then, is a simple matter of walking the window
  132.     list and drawing each successive window title.  But the menu
  133.     should include only application windows; for one thing, some DA
  134.     windows don't have titles.  So the trip through the window list
  135.     will skip over windows that aren't “userKind”.
  136.     
  137. *******************************************************************)
  138.     
  139.     procedure menudraw(themenu: MenuHandle; var menurect: Rect);
  140.         
  141.         var
  142.             height            :    integer;
  143.             width                :    integer;
  144.             therect            :    Rect;
  145.             thewindow        :    WindowPeek;
  146.         
  147.         begin
  148.             
  149.             height := menurect.top + 12;
  150.             width := menurect.left + 12;
  151.             
  152.             MoveTo(width, height);
  153.             DrawString('Zoom Front Window');
  154.             MoveTo(menurect.right - CharWidth('W') - 15, height);
  155.             DrawChar(chr(17));
  156.             DrawChar('W');
  157.             
  158.             if not BitTst(@themenu^^.enableFlags, 30) then begin
  159.                 PenPat(QDglobals^.gray);
  160.                 PenMode(patBic);
  161.                 with menurect do
  162.                     SetRect(therect, left, top, right, top + 16);
  163.                 PaintRect(therect);
  164.                 PenNormal;
  165.             end;
  166.             
  167.             height := height + 16;
  168.             MoveTo(menurect.left, menurect.top + 24);
  169.             Line(menurect.right - menurect.left, 0);
  170.             
  171.             thewindow := WindowPeek(longpointer(windowlist)^);
  172.             while thewindow <> nil do
  173.                 with thewindow^ do begin
  174.                     if visible and (windowkind = userKind) then begin
  175.                         height := height + 16;
  176.                         MoveTo(width, height);
  177.                         DrawString(titlehandle^^);
  178.                     end;
  179.                     thewindow := nextwindow;
  180.                 end;
  181.         
  182.         end;
  183.     
  184. (*******************************************************************
  185.     
  186.     menuchoose
  187.     ----------
  188.     
  189.     This routine is passed the mouse position, and sets the
  190.     “whichitem” parameter to the corresponding menu item.
  191.     
  192.     Since all the menu items are the same height, it's easy to
  193.     determine which one the mouse is in - provided it's somewhere
  194.     in the menu.  If that item is disabled, however, its number
  195.     should not be returned; instead the routine should return zero.
  196.     
  197.     Finally, if the mouse is in an active item, and that item is
  198.     different from the original value of “whichitem”, then the old
  199.     item should be un-highlighted, and the new one highlighted.
  200.     
  201. *******************************************************************)
  202.     
  203.     procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
  204.                     hitpoint : Point; var whichitem : integer);
  205.         
  206.         var
  207.             theitem            :    integer;
  208.             therect            :    Rect;
  209.         
  210.         begin
  211.             
  212.             if PtInRect(hitpoint, menurect) then
  213.                 theitem := 1 + ((hitpoint.v - menurect.top) div 16)
  214.             else
  215.                 theitem := 0;
  216.             
  217.             if not BitTst(@themenu^^.enableFlags, 31 - theitem) then
  218.                 theitem := 0;
  219.             
  220.             if theitem <> whichitem then begin
  221.                 
  222.                 therect := menurect;
  223.                 therect.bottom := therect.top + 16 * theitem;
  224.                 therect.top := therect.bottom - 16;
  225.                 InvertRect(therect);
  226.                 
  227.                 if whichitem > 0 then begin
  228.                     therect.bottom := menurect.top + 16 * whichitem;
  229.                     therect.top := therect.bottom - 16;
  230.                     InvertRect(therect);
  231.                 end;
  232.                 
  233.                 whichitem := theitem;
  234.             
  235.             end;
  236.         
  237.         end;
  238.     
  239. (*******************************************************************
  240.     
  241.     menusize
  242.     --------
  243.     
  244.     This routine calculates the dimensions of the menu rectangle.
  245.     
  246.     Similarly to the “menudraw” routine, this routine walks the
  247.     window list, and finds the widest item, to base the menu width
  248.     on.  The menu height is simply the sum of the item heights.
  249.     The results are stored in the MenuHandle.
  250.     
  251.     A note:  Odd things happened in this routine, with the string
  252.     width changing as windows were opened.  I can't figure why this
  253.     occurred, since Inside Mac says the Menu Manager sets the port
  254.     to the Window Manager port.  Anyway, the TextFont, TextSize and
  255.     TextFace calls cleared up the problem.
  256.     
  257. *******************************************************************)
  258.     
  259.     procedure menusize(themenu : MenuHandle);
  260.         
  261.         var
  262.             thewidth            :    integer;
  263.             theheight        :    integer;
  264.             thewindow        :    WindowPeek;
  265.             newwidth            :    integer;
  266.         
  267.         begin
  268.             
  269.             TextFont(systemFont);
  270.             TextSize(12);
  271.             TextFace([]);
  272.             
  273.             theheight := 32;
  274.             thewidth := StringWidth('Zoom Front Window')
  275.                             + CharWidth('W') + 39;
  276.             
  277.             thewindow := WindowPeek(longpointer(windowlist)^);
  278.             
  279.             while thewindow <> nil do
  280.                 with thewindow^ do begin
  281.                     if visible and (windowkind = userKind) then begin
  282.                         theheight := theheight + 16;
  283.                         newwidth := StringWidth(titlehandle^^) + 16;
  284.                         if newwidth > thewidth then
  285.                             thewidth := newwidth;
  286.                     end;
  287.                     thewindow := nextwindow;
  288.                 end;
  289.                 
  290.             themenu^^.menuHeight := theheight;
  291.             themenu^^.menuWidth := thewidth;
  292.         
  293.         end;
  294.     
  295. (******************************************************************)
  296.     
  297. end.
  298.     
  299. (******************************************************************)
  300.